Slight issue with plugin's toolbar bitmap when switching light/dark mode
-
Minor cosmetic thing with my plugin using, with Lazarus, rdipardos Notepad++ Plugin Template for Delphi & Lazarus.
A toolbar icon (better: bitmap; i checked a .bmp file will be used in fact) looks not so good in dark mode (light gray background. Somehow acceptable, but not perfect).As a kind of reference i checked against a C++ written plugin (funap’s explorer plugin: https://github.com/funap/npp-explorer-plugin), where it’s behaving better when switching between light and dark, and picked up, for test, the icons and bitmaps from there, especially “explore.bmp” from the “res”-subfolder.
I made a copy of explore.bmp -> explore_dark.bmp, spent it a dark background and added it to the plugin’s resource file:
TB_BMP BITMAP "Resources\\explore.bmp" TB_DM_BMP BITMAP "Resources\\explore_dark.bmp"
Then i adapted rdipardo’s code as follows:
Original:
https://bitbucket.org/rdipardo/delphiplugintemplate/src/default/Source/Units/HelloWorldPlugin.pasSee the test changes via “// **** Added”:
procedure THelloWorldPlugin.DoNppnToolbarModification; var tb: TToolbarIcons; tbDark: TTbIconsDarkMode; HTbBmp: HBITMAP; HTIcon: HICON; hHDC: HDC; bmpX, bmpY, icoX, icoY: Integer; begin tb := Default (TToolbarIcons); tbDark := Default (TTbIconsDarkMode); hHDC := 0; try hHDC := GetDC(THandle(Nil)); bmpX := MulDiv(16, GetDeviceCaps(hHDC, LOGPIXELSX), 96); bmpY := MulDiv(16, GetDeviceCaps(hHDC, LOGPIXELSY), 96); icoX := MulDiv(32, GetDeviceCaps(hHDC, LOGPIXELSX), 96); icoY := MulDiv(32, GetDeviceCaps(hHDC, LOGPIXELSY), 96); finally ReleaseDC(THandle(Nil), hHDC); end; // **** A change is done here: if self.IsDarkModeEnabled then // **** Added, for to assure to load a more appropriate bitmap for the toolbar for dark mode (without gray background) HTbBmp := LoadImage(Hinstance, 'TB_DM_BMP', IMAGE_BITMAP, bmpX, bmpY, 0) // **** Added else // **** Added HTbBmp := LoadImage(Hinstance, 'TB_BMP', IMAGE_BITMAP, bmpX, bmpY, 0); HTIcon := LoadImage(Hinstance, 'TB_ICON', IMAGE_ICON, icoX, icoY, (LR_DEFAULTSIZE or LR_LOADMAP3DCOLORS)); tb.ToolbarBmp := HTbBmp; tb.ToolbarIcon := HTIcon; tbDark.ToolbarBmp := HTbBmp; tbDark.ToolbarIcon := HTIcon; if self.SupportsDarkMode then begin tbDark.ToolbarIconDarkMode := LoadImage(Hinstance, 'TB_DM_ICON', IMAGE_ICON, icoX, icoY, (LR_DEFAULTSIZE or LR_LOADMAP3DCOLORS)); SendNppMessage(NPPM_ADDTOOLBARICON_FORDARKMODE, CmdIdFromDlgId(DlgMenuId), @tbDark); end else SendNppMessage(NPPM_ADDTOOLBARICON_DEPRECATED, CmdIdFromDlgId(DlgMenuId), @tb); end;
That works fine now so far when restarting NPP either in dark or in light mode.
But when switching the mode during a session - using Settings > Options > Dark mode - it has no effect (until i restart).
Because THelloWorldPlugin.DoNppnToolbarModification; won’t be called when doing this mode switch.So i added another change: explicitely triggering DoNppnToolbarModification when NPPN_DARKMODECHANGED notification happens:
procedure THelloWorldPlugin.BeNotified(sn: PSciNotification); begin inherited BeNotified(sn); if HWND(sn^.nmhdr.hwndFrom) = self.NppData.NppHandle then begin case sn.nmhdr.code of NPPN_DARKMODECHANGED: begin Self.DoNppnToolbarModification; // **** Added, for to assure that each the appropriate bitmap for the toolbar will be loaded when the mode is switched if Assigned(HelloWorldDockingForm) then begin HelloWorldDockingForm.ToggleDarkMode; end;
DoNppnToolbarModification will be called now when a session’s mode switch happens, the correct bitmap will be loaded (‘TB_BMP’ for light mode, ‘TB_DM_BMP’ for dark mode) … but the change cannot be seen in the toolbar itself (until i restart).
What might i miss ??
Attached the both bitmaps i used for test.
  -
-
@klaus101 said in Slight issue with plugin's toolbar bitmap when switching light/dark mode:
DoNppnToolbarModification will be called now when a session’s mode switch happens…
Plugins have just one opportunity to register toolbar icons when
NPPN_TBMODIFICATION
fires at application startup, so every icon resource handle must be provided in the body ofDoNppnToolbarModification
, regardless of the user’s active theme setting.DoNppnToolbarModification
is called implicitly by the ancestor class; you simply have to implement it. The internal theme switching logic of Notepad++ will select the appropriate icon by itself.There’s some updated documentation to look at also.
-
@rdipardo
thanks for the reply! Btw, for not to be misunderstood, i don’t think of a bug, i think i’m missing something general, so my post here.DoNppnToolbarModification is called implicitly by the ancestor class ; you simply have to implement it.
Yes of course, that’s given, called by TNppPlugin.BeNotified:
case sn.nmhdr.code of NPPN_TBMODIFICATION: begin self.DoNppnToolbarModification;
and implemented just equivalently to the demo, as shown above.
every icon resource handle must be provided in the body of DoNppnToolbarModification, regardless of the user’s active theme setting.
My first thought had been to do exactly that, via something like (which appears to be very obvious):
HTbBmp := LoadImage(Hinstance, 'TB_BMP', IMAGE_BITMAP, bmpX, bmpY, 0); HTbBmpDark := LoadImage(Hinstance, 'TB_DM_BMP', IMAGE_BITMAP, bmpX, bmpY, 0); // Separate variable here ... tb.ToolbarBmp := HTbBmp; tbDark.ToolbarBmp := HTbBmpDark;
Just analoguesly as it’s done in funap’s explorer plugin (Explorer.cpp), shortened:
g_explorerIcons.hToolbarBmp = (HBITMAP) ::LoadImage(g_hInst, MAKEINTRESOURCE(IDB_TB_EXPLORER), IMAGE_BITMAP, smallIconSize.cx, smallIconSize.cy, LR_LOADMAP3DCOLORS); g_explorerIcons.hToolbarIconDarkMode = (HICON) ::LoadImage(g_hInst, MAKEINTRESOURCE(IDI_TB_FLUENT_EXPLORER_DARKMODE), IMAGE_ICON, smallIconSize.cx, smallIconSize.cy, LR_LOADMAP3DCOLORS); ::SendMessage(g_nppData._nppHandle, NPPM_ADDTOOLBARICON_DEPRECATED, (WPARAM)funcItem[DOCKABLE_EXPLORER_INDEX]._cmdID, (LPARAM)&g_explorerIcons);
(but here it can be seen that for dark mode a ‘fluent’ item is loaded. A different story).
But it simply does not work as expected. We’ll see the darkened bitmap in dark as well as in light mode. and i don’t understand why not.
So my second approach as show in the OP.
In short, i think it sums up to the general question: is it possible to define separate toolbar bitmaps for dark and light as small standard symbols, and will they re-picked by a settings mode switch?
-
@rdipardo , @PeterJones ,
Don’t know if this question can be answered. But besides that i was wondering, why at all - as underlying reason for the question itself - the rendering of the same toolbar bitmap looked so different: in funap’s explorer plugin fine, in my test project being grayed backgrounded in dark mode.After some thoughts & trials i found the solution:
// -- Replace: HTbBmp := LoadImage(Hinstance, 'TB_BMP', IMAGE_BITMAP, bmpX, bmpY, 0) // -- by: HTbBmp := LoadImage(Hinstance, 'TB_BMP', IMAGE_BITMAP, bmpX, bmpY, LR_LOADMAP3DCOLORS);
No more need for to provide two different bitmaps …
(There’s still a difference between both: in my case the bitmap shows a kind of ‘focus rectangle’ around when the plugin is active, whereas the other has not. But i don’t find it disturbing at all, and it’s presumably by a different setting. But maybe anybody knows why, simply for understanding).